
#include "MyWord.h"
#include <sstream>
#include <assert.h>

//運算元，如果有想要新處理的也必須加在這


std::string MyWord::ariths[]={	"SUM","ADD","SUB","MUL","DIV",
							"SQRT","POW",
							"SIN","COS","TAN","ASIN","ACOS","ATAN",
							"EXP","LOG","LOG10",
							"CEIL","FLOOR","ABS","MOD","ABS",
							"INT"};
int MyWord::ariths_num[]={	0,2,2,2,2,
							1,2,
							1,1,1,1,1,1,
							1,1,1,
							1,1,1,2,1,
							1};
int MyWord::arithNumber=22;

MyWord::MyWord(std::string type){

	this->_type=type;
	this->_childs=NULL;
	this->_value_string="";
	this->_value_double=0;
	this->_value_int=0;
	this->_value_float=0;
}

MyWord::MyWord(std::string type,std::string value){

	this->_type=type;
	this->_childs=NULL;
	//將int、double、ID對應到不同的型態
	this->_value_string="";
	this->_value_double=0;
	this->_value_int=0;
	this->_value_float=0;
	normalize(value);

}

MyWord::MyWord(MyWord& token){

	assert(&token);

	this->_type=token._type;
	this->_value_string=token._value_string;
	this->_value_double=token._value_double;
	this->_value_int=token._value_int;
	this->_childs=token._childs;
}

MyWord::~MyWord(){
	
// 	//當需要移除
// 	if(this->_childs!=NULL){
// 		vector<MyWord*>::iterator itr=this->_childs->begin();
// 		for(;itr!=this->_childs->end();itr++){
// 			delete (*itr);
// 		}	
// 		delete this->_childs;
// 	}

}

void MyWord::normalize(std::string value){

	assert(!value.empty());

	if(this->_type=="int"){
		std::istringstream(value)>>_value_int;
	}
	else if(this->_type=="double"){
		std::istringstream(value)>>_value_double;
	}
	else if(this->_type=="float"){
		std::istringstream(value)>>_value_float;
	}
	else if(this->_type=="id"||this->_type=="arith"){
		this->_value_string=value;
	}
}

MyWord& MyWord::operator +=(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	if(this->_type=="int"&&token._type=="int"){
		this->_value_int+=token._value_int;
	}
	else if(this->_type=="int"&&token._type=="double"){
		this->_value_double=this->_value_int+token._value_double;
		this->_type="double";
	}
	else if(this->_type=="int"&&token._type=="float"){
		this->_value_int+=token._value_float;
	}
	else if(this->_type=="double"&&token._type=="int"){
		this->_value_double+=token._value_int;
	}
	else if(this->_type=="double"&&token._type=="double"){
		this->_value_double+=token._value_double;
	}
	else if(this->_type=="double"&&token._type=="float"){
		this->_value_double+=token._value_float;
	}
	else if(this->_type=="float"&&token._type=="int"){
		this->_value_float+=token._value_int;
	}
	else if(this->_type=="float"&&token._type=="double"){
		this->_value_float+=token._value_double;
	}
	else if(this->_type=="float"&&token._type=="float"){
		this->_value_float+=token._value_float;
	}

	return *this;
}

MyWord& MyWord::operator -=(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	if(this->_type=="int"&&token._type=="int"){
		this->_value_int-=token._value_int;
	}
	else if(this->_type=="int"&&token._type=="double"){
		this->_value_double=this->_value_int-token._value_double;
		this->_type="double";
	}
	else if(this->_type=="int"&&token._type=="float"){
		this->_value_int-=token._value_float;
	}
	else if(this->_type=="double"&&token._type=="int"){
		this->_value_double-=token._value_int;
	}
	else if(this->_type=="double"&&token._type=="double"){
		this->_value_double-=token._value_double;
	}
	else if(this->_type=="double"&&token._type=="float"){
		this->_value_double-=token._value_float;
	}
	else if(this->_type=="float"&&token._type=="int"){
		this->_value_float-=token._value_int;
	}
	else if(this->_type=="float"&&token._type=="double"){
		this->_value_float-=token._value_double;
	}
	else if(this->_type=="float"&&token._type=="float"){
		this->_value_float-=token._value_float;
	}

	return *this;

}

MyWord& MyWord::operator *=(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	if(this->_type=="int"&&token._type=="int"){
		this->_value_int*=token._value_int;
	}
	else if(this->_type=="int"&&token._type=="double"){
		this->_value_double=this->_value_int*token._value_double;
		this->_type="double";
	}
	else if(this->_type=="int"&&token._type=="float"){
		this->_value_int*=token._value_float;
	}
	else if(this->_type=="double"&&token._type=="int"){
		this->_value_double*=token._value_int;
	}
	else if(this->_type=="double"&&token._type=="double"){
		this->_value_double*=token._value_double;
	}
	else if(this->_type=="double"&&token._type=="float"){
		this->_value_double*=token._value_float;
	}
	else if(this->_type=="float"&&token._type=="int"){
		this->_value_float*=token._value_int;
	}
	else if(this->_type=="float"&&token._type=="double"){
		this->_value_float*=token._value_double;
	}
	else if(this->_type=="float"&&token._type=="float"){
		this->_value_float*=token._value_float;
	}

	return *this;
}

MyWord& MyWord::operator /=(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	if(this->_type=="int"&&token._type=="int"){
		if(token._value_int == 0){
			this->_value_int = 0;
		}
		else if(this->_value_int%token._value_int==0){
			this->_value_int/=token._value_int;			
		}
		else{
			this->_value_double=(float)this->_value_int/(float)token._value_int;
			this->_type="double";
		}
	}
	else if(this->_type=="int"&&token._type=="double"){
		this->_value_double=this->_value_int/token._value_double;
		this->_type="double";
	}
	else if(this->_type=="int"&&token._type=="float"){
		this->_value_double=this->_value_int/token._value_float;
		this->_type="double";
	}
	else if(this->_type=="double"&&token._type=="int"){
		this->_value_double/=token._value_int;
	}
	else if(this->_type=="double"&&token._type=="double"){
		this->_value_double/=token._value_double;
	}
	else if(this->_type=="double"&&token._type=="float"){
		this->_value_double/=token._value_float;
	}
	else if(this->_type=="float"&&token._type=="int"){
		this->_value_float/=token._value_int;
		this->_type="double";
	}
	else if(this->_type=="float"&&token._type=="double"){
		this->_value_float/=token._value_double;
		this->_type="double";
	}
	else if(this->_type=="float"&&token._type=="float"){
		this->_value_float/=token._value_float;
		this->_type="double";
	}
	return *this;
}


MyWord& MyWord::operator +(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	MyWord* current=new MyWord(*this);

	*current+=token;

	return *current;
}

MyWord& MyWord::operator -(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	MyWord* current=new MyWord(*this);

	*current-=token;

	return *current;
}

MyWord& MyWord::operator -(){

	typeCheck(this);

	if(this->_type=="int"){
		this->_value_int*=-1;
	}
	else if(this->_type=="double"){
		this->_value_double*=-1;
	}
	else if(this->_type=="float"){
		this->_value_float*=-1;
	}
	return *this;
}

MyWord& MyWord::operator *(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	MyWord* current=new MyWord(*this);

	*current*=token;

	return *current;
}

MyWord& MyWord::operator /(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	MyWord* current=new MyWord(*this);

	*current/=token;

	return *current;
}

MyWord& MyWord::operator =(MyWord& token){

	typeCheck(this);
	typeCheck(&token);

	return *this;
}

void MyWord::typeCheck(MyWord* token){
	
	assert(token->_type=="double"||token->_type=="int"||token->_type=="float");
}

